package tcp_proxy_router

import (
	"context"
	"fmt"
	"log"
	"net"

	"go_gateway/dao"
	"go_gateway/reverse_proxy"
	"go_gateway/tcp_proxy_middleware"
	"go_gateway/tcp_server"
)

/*
TCP 代理服务器的实现
- 长连接、双向流
- 按端口区分服务

工作流程:
	1. 客户端连接到 TCP 代理端口
	2. 进入中间件处理链:
	└─ 流量统计 → 记录指标
	└─ 流量限制 → 检查是否超限
	└─ 白名单 → 验证客户端 IP
	└─ 黑名单 → 拦截恶意 IP
	3. 负载均衡选择后端服务器
	4. 建立到后端服务器的连接
	5. 双向数据转发
*/

var tcpServerList = []*tcp_server.TcpServer{}

type tcpHandler struct {
}

func (t *tcpHandler) ServeTCP(ctx context.Context, src net.Conn) {
	src.Write([]byte("tcpHandler\n"))
}

func TcpServerRun() {
	// 1.从内存中获取所有 TCP 类型的服务配置
	serviceList := dao.ServiceManagerHandler.GetTcpServiceList()

	for _, serviceItem := range serviceList {
		tempItem := serviceItem
		// 2.每个 TCP 服务在独立的 goroutine 中运行
		go func(serviceDetail *dao.ServiceDetail) {
			// 构建监听地址
			addr := fmt.Sprintf(":%d", serviceDetail.TCPRule.Port)
			// 3.获取负载均衡器
			rb, err := dao.LoadBalancerHandler.GetLoadBalancer(serviceDetail)
			if err != nil {
				log.Fatalf(" [INFO] GetTcpLoadBalancer %v err:%v\n", addr, err)
				return
			}

			// 4.构建路由及设置中间件
			router := tcp_proxy_middleware.NewTcpSliceRouter()
			router.Group("/").Use(
				tcp_proxy_middleware.TCPFlowCountMiddleware(), // 流量统计
				tcp_proxy_middleware.TCPFlowLimitMiddleware(), // 流量限制
				tcp_proxy_middleware.TCPWhiteListMiddleware(), // 白名单
				tcp_proxy_middleware.TCPBlackListMiddleware(), // 黑名单
			)

			// 处理流程：
			// 1. 客户端连接 → TCP服务器
			// 2. 中间件链处理（流量统计、限流、黑白名单）
			// 3. 反向代理 → 后端服务器

			// 5.构建回调路由处理器
			routerHandler := tcp_proxy_middleware.NewTcpSliceRouterHandler(
				func(c *tcp_proxy_middleware.TcpSliceRouterContext) tcp_server.TCPHandler {
					// 基于负载均衡器的 TCP 反向代理，将请求转发到后端服务器集群
					return reverse_proxy.NewTcpLoadBalanceReverseProxy(c, rb)
				}, router)

			// 将服务配置信息传递到处理链中，中间件可以通过上下文获取服务详情
			baseCtx := context.WithValue(context.Background(), "service", serviceDetail)
			// 6.创建 TCP 服务器
			tcpServer := &tcp_server.TcpServer{
				Addr:    addr,          // 监听地址
				Handler: routerHandler, // 中间件处理器
				BaseCtx: baseCtx,       // 包含服务配置的上下文
			}

			// 7.启动服务器
			tcpServerList = append(tcpServerList, tcpServer)
			log.Printf(" [INFO] tcp_proxy_run %v\n", addr)
			if err := tcpServer.ListenAndServe(); err != nil && err != tcp_server.ErrServerClosed {
				log.Fatalf(" [INFO] tcp_proxy_run %v err:%v\n", addr, err)
			}
		}(tempItem)
	}
}

func TcpServerStop() {
	for _, tcpServer := range tcpServerList {
		tcpServer.Close()
		log.Printf(" [INFO] tcp_proxy_stop %v stopped\n", tcpServer.Addr)
	}
}
